home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / self / contrib.lha / contrib / self-mode / self-mode.shar / self-mode.el < prev    next >
Encoding:
Text File  |  1993-07-24  |  9.8 KB  |  302 lines

  1. ;; Self mode editing commands for Emacs, a first cut...
  2. ;; Mar 11, 1992 Stuart Williams, williams@cs.washington.edu
  3. ;; Let me know if you fix stuff.
  4.  
  5. ;; Extended by Craig Chambers, Jan 30, 1993.
  6. ;;   Indent statement continuation lines
  7. ;;   Indent comments and multi-line comments (sort of)
  8.  
  9. ;; Extended by Urs Hoelzle, March 21, 1993.
  10. ;;   Added Lucid emacs highlighting (thanks to Lars Bak)
  11.  
  12. ;;
  13. ;; Hacked by Michael Richardson <mcr@physics.carleton.ca> to interact
  14. ;; with self.el, an inferior self mode.
  15. ;;  - Added M-C-x to do send-self-object.
  16. ;;  - Added beginning-of-object/end-of-object for above.
  17. ;;  - Also added backward-object/forward-object (not currently bound
  18. ;;    to any specific key. I tend to bind them to function keys..)
  19. ;;  - Stuff it into RCS.
  20.  
  21. ;; To do:
  22. ;; - Parsing for indentation is currently done starting at the top of the
  23. ;;   whole file (yuck)!  It should start parsing somewhere closer.
  24. ;; - Indentation is absolute from parsing the whole file and the left margin,
  25. ;;   it should be relative to the enclosing block of code.
  26. ;; - right bracket and parethesis should only call self-indent if they're
  27. ;;   at the beginning of a line, not at the end.
  28. ;; - A second tab in a row could be smarter and insert a tab
  29.  
  30. ;
  31. ; $Id: self-mode.el,v 1.1 1993/05/14 21:11:48 richards Rel $
  32. ; $Log: self-mode.el,v $
  33. ; Revision 1.1  1993/05/14  21:11:48  richards
  34. ; Initial revision
  35. ;
  36. ;
  37.  
  38. (provide 'self-mode)
  39.  
  40. (defvar self-mode-abbrev-table nil
  41.   "Abbrev table for use in self-mode buffers.")
  42. (define-abbrev-table 'self-mode-abbrev-table ())
  43.  
  44. (defvar self-mode-map ()
  45.   "Keymap used in Self mode.")
  46.  
  47. (defun self-mode-commands (map) 
  48.   "Adds the self commands to a keymap."
  49.   (define-key map "\177" 'backward-delete-char-untabify)
  50.   (define-key map "\t" 'self-tab-indent)
  51.   (define-key map "\C-j" 'newline-and-indent)
  52.   (define-key map "\M-\C-x" 'self-send-object)
  53.   ;; uncomment the next 4 lines to turn off automatic indentation
  54.   (define-key map "(" 'electric-self-brace)
  55.   (define-key map ")" 'electric-self-brace)
  56.   (define-key map "[" 'electric-self-brace)
  57.   (define-key map "]" 'electric-self-brace))
  58.  
  59. (if self-mode-map
  60.     ()
  61.   (progn
  62.     (setq self-mode-map (make-sparse-keymap))
  63.     (self-mode-commands self-mode-map)))
  64.  
  65. (defvar self-mode-syntax-table nil
  66.   "Syntax table in use in Self-mode buffers.")
  67.  
  68. (if self-mode-syntax-table
  69.     ()
  70.   (setq self-mode-syntax-table (make-syntax-table))
  71.   (modify-syntax-entry ?\( "()  " self-mode-syntax-table)
  72.   (modify-syntax-entry ?\) ")(  " self-mode-syntax-table)
  73.   (modify-syntax-entry ?\[ "(]  " self-mode-syntax-table)
  74.   (modify-syntax-entry ?\] ")[  " self-mode-syntax-table)
  75.   (modify-syntax-entry ?\| "$|  " self-mode-syntax-table)
  76.  
  77.   ;; treat double quote as string,
  78.   ;; since it can't be both comment start and end
  79.   (modify-syntax-entry ?\" "\"   " self-mode-syntax-table)
  80.  
  81.   ;; apostrophe is used for strings
  82.   (modify-syntax-entry ?\' "\"   " self-mode-syntax-table)
  83.  
  84.   ;; space, tab, newline, and formfeed are whitespace:
  85.   (modify-syntax-entry ?   "    " self-mode-syntax-table)
  86.   (modify-syntax-entry ?\t "    " self-mode-syntax-table)
  87.   (modify-syntax-entry ?\n "    " self-mode-syntax-table)
  88.   (modify-syntax-entry ?\f "    " self-mode-syntax-table)
  89.  
  90.   (modify-syntax-entry ?\\ "\\  " self-mode-syntax-table)
  91.  
  92.   (modify-syntax-entry ?+ "." self-mode-syntax-table)
  93.   (modify-syntax-entry ?- "." self-mode-syntax-table)
  94.   (modify-syntax-entry ?= "." self-mode-syntax-table)
  95.   (modify-syntax-entry ?% "." self-mode-syntax-table)
  96.   (modify-syntax-entry ?< "." self-mode-syntax-table)
  97.   (modify-syntax-entry ?> "." self-mode-syntax-table)
  98.   (modify-syntax-entry ?& "." self-mode-syntax-table))
  99.  
  100. (defconst self-indent-level 4
  101.   "*Indentation of Self statements with respect to containing block.")
  102.  
  103. (defconst self-continuation-indent-level 4
  104.   "*Indentation of Self statement continuations with respect to statement start.")
  105.  
  106. (defun self-mode ()
  107.   "Major mode for editing Self code."
  108.   (interactive)
  109.   (kill-all-local-variables)
  110.   (use-local-map self-mode-map)
  111.   (setq major-mode 'self-mode)
  112.   (setq mode-name "Self")
  113.   (self-mode-variables)
  114.   (run-hooks 'self-mode-hook))
  115.  
  116. (defun self-mode-variables ()
  117.   (setq local-abbrev-table self-mode-abbrev-table)
  118.   (set-syntax-table self-mode-syntax-table)
  119.   (make-local-variable 'paragraph-start)
  120.   (setq paragraph-start (concat "^$\\|" page-delimiter))
  121.   (make-local-variable 'paragraph-separate)
  122.   (setq paragraph-separate paragraph-start)
  123.   (make-local-variable 'paragraph-ignore-fill-prefix)
  124.   (setq paragraph-ignore-fill-prefix t)
  125.   (make-local-variable 'indent-line-function)
  126.   (setq indent-line-function 'self-tab-indent)
  127.   (make-local-variable 'require-final-newline)
  128.   (setq require-final-newline t))
  129.  
  130.  
  131. (defun self-tab-indent ()
  132.   "Indent current line as Self code, even if an empty line."
  133.   (interactive)
  134.   (let ((indent-column (self-indent-line))) ; how far should we indent
  135.     (if (and (numberp indent-column)
  136.          (< (current-column) indent-column)) ; move cursor to right only
  137.     (move-to-column indent-column))))
  138.  
  139. (defun self-indent-line ()
  140.   "Indent current line as Self code."
  141.   (interactive)
  142.   (let ((indent-size (calculate-self-indent)))
  143.     (if (numberp indent-size)        ; else don't indent
  144.     (save-excursion
  145.       (beginning-of-line)
  146.       (skip-chars-forward " \t")
  147.       (if (/= (current-column) indent-size)
  148.           (progn        ; don't change unless we have to
  149.         (delete-horizontal-space)
  150.         (indent-to-column indent-size)))))
  151.     indent-size))
  152.  
  153. (defun self-indent-region (start end)
  154.   "Indent the current region as Self code."
  155.   (interactive "r")
  156.   (save-excursion
  157.     (let ((end-marker (copy-marker end)))
  158.       (goto-char start)
  159.       (while (< (point) (marker-position end-marker))
  160.     (forward-line)
  161.     (self-indent-line)))))
  162.  
  163. (defun self-indent-buffer ()
  164.   "Indent the current buffer as Self code."
  165.   (interactive)
  166.   (save-excursion
  167.     (self-indent-region (point-min) (point-max))))
  168.  
  169. (defun calculate-self-indent ()
  170.   "Calculate correct indentation for a line of Self code.
  171. Returns an integer or nil if inside a string."
  172.   (save-excursion
  173.     (beginning-of-line)
  174.     (skip-chars-forward " \t")
  175.     (let (state paren-depth containing-sexp in-comment in-string)
  176.       (setq state (parse-partial-sexp 1 (point))) ;; this should *not* be 1
  177.  
  178.       (setq paren-depth (nth 0 state))
  179.       (setq containing-sexp (nth 1 state))
  180.       (setq in-comment (nth 3 state))    ;; documentation has these two backwards
  181.       (setq in-string (nth 4 state))
  182.  
  183.       (cond
  184.        (in-string
  185.        ;; If inside string return nil (don't indent);
  186.     nil)
  187.  
  188.        (in-comment
  189.     ;; If inside comment indent equal to enclosing statement, plus 1 to
  190.     ;; skip the enclosing quote char
  191.     ;; (really should indent equal to the first char after the quote,
  192.     ;;  to line up text nicely)
  193.     (1+ (* self-indent-level paren-depth)))
  194.  
  195.        ((null containing-sexp)
  196.     ;; Line is at top level.
  197.     ;; Because of paren-counting at top-level, never have a continuation
  198.     ;; line at the top-level.
  199.     ;; No indentation at top-level.
  200.     0)
  201.        
  202.        ((or
  203.      (looking-at ")")
  204.      (looking-at "]")
  205.      (looking-at "|[ \t]*)")
  206.      (looking-at "|[ \t]*]"))
  207.     ;; line starts a statement, and should back up indentation, too
  208.     (* self-indent-level (1- paren-depth)))
  209.     
  210.        (t
  211.     ;; a nested line; check whether it starts a statement or continues one
  212.     (cond ((self-starts-statement containing-sexp)
  213.            ;; starts statement
  214.            (* self-indent-level paren-depth))
  215.           (t
  216.            ;; continues statement; indent some more
  217.            (+ (* self-indent-level paren-depth)
  218.           self-continuation-indent-level))))))))
  219.  
  220. (defun self-starts-statement (lim)
  221.   (save-excursion
  222.     (catch 'done
  223.       (while t
  224.     (skip-chars-backward " \t\n\f" lim)
  225.     (if (<= (point) lim) (throw 'done t))
  226.     (backward-char)
  227.     (cond ((looking-at "\"")
  228.            (progn
  229.          (search-backward "\"" lim 'move-if-fail)
  230.          (if (<= (point) lim) (throw 'done t))))
  231.           (t (throw 'done
  232.             (or
  233.              (looking-at "\\.")
  234.              (looking-at "(")
  235.              (looking-at "\\[")
  236.              (looking-at "|")))))))))
  237.  
  238. (defun electric-self-brace (arg)
  239.   "Insert character and correct line's indentation."
  240.   (interactive "P")
  241.   (insert last-command-char)        ; insert arg, in a way that won't blink
  242.   (self-indent-line)            ; indent it
  243.   (delete-char -1)            ; delete and reinsert arg so it blinks
  244.   (self-insert-command (prefix-numeric-value arg)))
  245.  
  246. (defun end-of-object ()
  247.   "Move the point to the spot where the object ends."
  248. ; I assume that with normal formatting, this is a line that has
  249. ; just a (|) on it.
  250.   (interactive)
  251.   (beginning-of-line)
  252.   (while (and (< (point) (point-max))
  253.           (not (looking-at ")"))
  254.           (not (looking-at "]"))
  255.           (not (looking-at "|[ \t]*)"))
  256.           (not (looking-at "|[ \t]*]")))
  257.     (forward-line)
  258.     (beginning-of-line))
  259.   (if (< (point) (point-max)) (forward-line)))
  260.  
  261. (defun beginning-of-object ()
  262.   "Move the point to the spot where the object begins."
  263. ; We do this by going upwards, looking for the end of previous object.
  264. ; An alternative way is to look for a line that doesn't start with a space.
  265. ; Time will tell what the better method is.
  266.   (interactive)
  267.   (beginning-of-line)
  268.   (while (and (> (point) (point-min))
  269.           (not (looking-at ")"))
  270.           (not (looking-at "]"))
  271.           (not (looking-at "|[ \t]*)"))
  272.           (not (looking-at "|[ \t]*]")))
  273.     (forward-line -1)
  274.     (beginning-of-line))
  275. ; don't go forward at the top.
  276.   (if (> (point) (point-min)) (forward-line)))
  277.  
  278. (defun forward-object (&optional num)
  279.   "moves forward in the file by arg objects"
  280.   (interactive "p")
  281.   (if (not num) (setq num 1))
  282.   (while (> num 0)
  283.     (end-of-object)
  284.     (setq num (- num 1))))
  285.   
  286. (defun backward-object (&optional num)
  287.   "moves backward in the file by arg objects"
  288.   (interactive "p")
  289.   (if (not num) (setq num 1))
  290.   (forward-line -1)
  291.   (while (> num 0)
  292.     (beginning-of-line)
  293.     (while (or (looking-at ")")
  294.            (looking-at "]")
  295.            (looking-at "|[ \t]*)")
  296.            (looking-at "|[ \t]*]"))
  297.       (forward-line -1))
  298.     (beginning-of-object)
  299.     (setq num (- num 1))))
  300.  
  301.